#include "GameEngine/SkyBox.h"

#define SetVertex(arr, i, x, y, z) arr[i*3+0]=x; arr[i*3+1]=y; arr[i*3+2]=z;
#define SetUV(arr, i, x, y) arr[i*2+0]=x; arr[i*2+1]=y;

SkyBox::SkyBox(float scale, bool adjustUV, int textureSize)
{
	this->scale=scale;
	char *filename = new char[2048];
	for (int i=0; i<6; i++){
		memset(filename, 0, 2048 * sizeof(char));
		sprintf(filename, "RES/skybox%d.pvr", (i+1));
		m_ui32SkyboxTex[i]=TextureManager::loadTextureFromFile(filename);
		if(!m_ui32SkyboxTex[i])
		{
			printf("**ERROR** Failed to load texture for skybox.\n");
		}
		::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}

	float unit = f2vt(1);
	float a0 = 0, a1 = unit;
	
	if (adjustUV)
	{
		float oneover = f2vt(1.0f / textureSize);
		a0 = VERTTYPEMUL(f2vt(4.0f), oneover);
		a1 = unit - a0;
	}
	
	// Front
	SetVertex(g_skyboxVertices, 0, -unit, +unit, -unit);
	SetVertex(g_skyboxVertices, 1, +unit, +unit, -unit);
	SetVertex(g_skyboxVertices, 2, -unit, -unit, -unit);
	SetVertex(g_skyboxVertices, 3, +unit, -unit, -unit);
	SetUV(g_skyboxUVs, 0, a0, a1);
	SetUV(g_skyboxUVs, 1, a1, a1);
	SetUV(g_skyboxUVs, 2, a0, a0);
	SetUV(g_skyboxUVs, 3, a1, a0);
	
	// Right
	SetVertex(g_skyboxVertices, 4, +unit, +unit, -unit);
	SetVertex(g_skyboxVertices, 5, +unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 6, +unit, -unit, -unit);
	SetVertex(g_skyboxVertices, 7, +unit, -unit, +unit);
	SetUV(g_skyboxUVs, 4, a0, a1);
	SetUV(g_skyboxUVs, 5, a1, a1);
	SetUV(g_skyboxUVs, 6, a0, a0);
	SetUV(g_skyboxUVs, 7, a1, a0);
	
	// Back
	SetVertex(g_skyboxVertices, 8 , +unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 9 , -unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 10, +unit, -unit, +unit);
	SetVertex(g_skyboxVertices, 11, -unit, -unit, +unit);
	SetUV(g_skyboxUVs, 8 , a0, a1);
	SetUV(g_skyboxUVs, 9 , a1, a1);
	SetUV(g_skyboxUVs, 10, a0, a0);
	SetUV(g_skyboxUVs, 11, a1, a0);
	
	// Left
	SetVertex(g_skyboxVertices, 12, -unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 13, -unit, +unit, -unit);
	SetVertex(g_skyboxVertices, 14, -unit, -unit, +unit);
	SetVertex(g_skyboxVertices, 15, -unit, -unit, -unit);
	SetUV(g_skyboxUVs, 12, a0, a1);
	SetUV(g_skyboxUVs, 13, a1, a1);
	SetUV(g_skyboxUVs, 14, a0, a0);
	SetUV(g_skyboxUVs, 15, a1, a0);
	
	// Top
	SetVertex(g_skyboxVertices, 16, -unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 17, +unit, +unit, +unit);
	SetVertex(g_skyboxVertices, 18, -unit, +unit, -unit);
	SetVertex(g_skyboxVertices, 19, +unit, +unit, -unit);
	SetUV(g_skyboxUVs, 16, a0, a1);
	SetUV(g_skyboxUVs, 17, a1, a1);
	SetUV(g_skyboxUVs, 18, a0, a0);
	SetUV(g_skyboxUVs, 19, a1, a0);
	
	// Bottom
	SetVertex(g_skyboxVertices, 20, -unit, -unit, -unit);
	SetVertex(g_skyboxVertices, 21, +unit, -unit, -unit);
	SetVertex(g_skyboxVertices, 22, -unit, -unit, +unit);
	SetVertex(g_skyboxVertices, 23, +unit, -unit, +unit);
	SetUV(g_skyboxUVs, 20, a0, a1);
	SetUV(g_skyboxUVs, 21, a1, a1);
	SetUV(g_skyboxUVs, 22, a0, a0);
	SetUV(g_skyboxUVs, 23, a1, a0);
	
	//for (int i=0; i<24*3; i++)
	//	g_skyboxVertices[i] = VERTTYPEMUL(g_skyboxVertices[i], f2vt(scale));
}

void SkyBox::draw(Camera* cam)
{
	::glEnableClientState(GL_VERTEX_ARRAY);
	::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	::glEnable(GL_TEXTURE_2D);

	/* Only use the texture color */
	::glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	
	::glMatrixMode(GL_PROJECTION);
	::glPushMatrix();
	::glMatrixMode(GL_MODELVIEW);
	::glPushMatrix();
	::glTranslatef(cam->cameraPos.x, cam->cameraPos.y, cam->cameraPos.z);
	::glScalef(scale,scale,scale);

	// Disable lighting
	::glDisable(GL_LIGHTING);
	
	::glFrontFace(GL_CCW);
	::glEnable(GL_CULL_FACE);
	::glCullFace(GL_BACK);
	
	::glRotatef(90,1,0,0);
	::glRotatef(180,0,1,0);
	for(int i = 0; i < 5; ++i)
	{
		::glBindTexture(GL_TEXTURE_2D, m_ui32SkyboxTex[i]);
		::glVertexPointer(3, VERTTYPEENUM, sizeof(float)*3, &g_skyboxVertices[i*4*3]);
		::glTexCoordPointer(2, VERTTYPEENUM, sizeof(float)*2, &g_skyboxUVs[i*4*2]);
		::glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	}
	
	::glMatrixMode(GL_MODELVIEW);
	::glPopMatrix();
	::glMatrixMode(GL_PROJECTION);
	::glPopMatrix();
}
